package Model;

import java.util.ArrayList;

public class Villager extends Being {
    // ATTRIBUTE

    private Clan myClan;

    // CONSTRUCTOR
    public Villager(int id, int speed, Location location, int visionRadius, Activity activity, Clan myClan) {
        super(id, speed, location, visionRadius, false);
        this.activity = activity;
        this.myClan = myClan;


        switch (activity) {
            case Hunter:
                this.setResourceBrought(new Resource(ResourceType.Food, 0));
                break;
            case Lumberjack:
                this.setResourceBrought(new Resource(ResourceType.Wood, 0));
                break;
            case Goldminer:
                this.setResourceBrought(new Resource(ResourceType.Gold, 0));
                break;
            case Stoneminer:
                this.setResourceBrought(new Resource(ResourceType.Stone, 0));
                break;
            default:
                break;
        }
    }

    // OWN FUNCTIONS
    public Action decideAction(ArrayList<Square> environmentInRadius, ArrayList<Square> directEnvironement) {
        DecisionMatrix decisionMatrix = new DecisionMatrix();
        ArrayList<DirectionWeighted> dangerDirection = dangerAround(environmentInRadius);
        ArrayList<DirectionWeighted> POIDirection = pointsOfInterestAround(environmentInRadius);
        ArrayList<DirectDirection> POIHandToHand = pointsOfIntestInHtH(directEnvironement);

        majMemory(environmentInRadius);

        //Ne passe pas par la decisionMatrix
        if (hasMaxRessource()) {
            //System.out.println("Has max Ressource");
            //System.out.println("Being position : ");
            //this.getLocation().displayInTerminal();
            this.setTargetLocation(this.myClan.getSquareQG().getLocation());
            boolean pathOK = validatePath();

            if (pathOK) {
                //decisionMatrix set weight to target direction
                //System.out.println("Path OK !!");
                DirectDirection nextDirection = this.getNextPathLocationDirection();
                if (!nextDirection.equals(DirectDirection.None)) {
                    Action action = new Action(nextDirection, 3);
                    //action.displayInTerminal();
                    return action;
                } else {
                    if (directEnvironement.contains(myClan.getSquareQG())) {
                        //System.out.println("Resource dropped");
                        myClan.dropFood(this);
                        //System.out.println("has resource after drop : " + this.hasMaxRessource());
                        this.setTargetLocation(null);
                    }
                }
            }
        }


        // CONSTRUCTION OF DECISION MATRIX
        // TREATMENT DANGER
        for (int i = 0; i < dangerDirection.size(); i++) {
            switch (dangerDirection.get(i).getDirection()) {
                case North:
                    decisionMatrix.setDecisionN(0, decisionMatrix.getDecisionN(0) + dangerDirection.get(i).getWeight());
                    decisionMatrix.setDecisionNE(0, decisionMatrix.getDecisionNE(0) + dangerDirection.get(i).getWeight());
                    decisionMatrix.setDecisionNO(0, decisionMatrix.getDecisionNO(0) + dangerDirection.get(i).getWeight());
                    break;

                case South:
                    decisionMatrix.setDecisionS(0, decisionMatrix.getDecisionS(0) + dangerDirection.get(i).getWeight());
                    decisionMatrix.setDecisionSE(0, decisionMatrix.getDecisionSE(0) + dangerDirection.get(i).getWeight());
                    decisionMatrix.setDecisionSO(0, decisionMatrix.getDecisionSO(0) + dangerDirection.get(i).getWeight());
                    break;

                case West:
                    decisionMatrix.setDecisionO(0, decisionMatrix.getDecisionO(0) + dangerDirection.get(i).getWeight());
                    decisionMatrix.setDecisionSO(0, decisionMatrix.getDecisionSO(0) + dangerDirection.get(i).getWeight());
                    decisionMatrix.setDecisionNO(0, decisionMatrix.getDecisionNO(0) + dangerDirection.get(i).getWeight());
                    break;

                case East:
                    decisionMatrix.setDecisionE(0, decisionMatrix.getDecisionE(0) + dangerDirection.get(i).getWeight());
                    decisionMatrix.setDecisionNE(0, decisionMatrix.getDecisionNE(0) + dangerDirection.get(i).getWeight());
                    decisionMatrix.setDecisionSE(0, decisionMatrix.getDecisionSE(0) + dangerDirection.get(i).getWeight());
                    break;

                default:
                    break;
            }
        }

        // TREATMENT POI
        for (int i = 0; i < POIDirection.size(); i++) {
            if (!POIDirection.isEmpty()) // secure test
            {
                switch (POIDirection.get(i).getDirection()) {
                    case North:
                        decisionMatrix.setDecisionN(1, decisionMatrix.getDecisionN(1) + POIDirection.get(i).getWeight());
                        decisionMatrix.setDecisionNE(1, decisionMatrix.getDecisionNE(1) + POIDirection.get(i).getWeight());
                        decisionMatrix.setDecisionNO(1, decisionMatrix.getDecisionNO(1) + POIDirection.get(i).getWeight());
                        break;

                    case South:
                        decisionMatrix.setDecisionS(1, decisionMatrix.getDecisionS(1) + POIDirection.get(i).getWeight());
                        decisionMatrix.setDecisionSE(1, decisionMatrix.getDecisionSE(1) + POIDirection.get(i).getWeight());
                        decisionMatrix.setDecisionSO(1, decisionMatrix.getDecisionSO(1) + POIDirection.get(i).getWeight());
                        break;

                    case West:
                        decisionMatrix.setDecisionO(1, decisionMatrix.getDecisionO(1) + POIDirection.get(i).getWeight());
                        decisionMatrix.setDecisionSO(1, decisionMatrix.getDecisionSO(1) + POIDirection.get(i).getWeight());
                        decisionMatrix.setDecisionNO(1, decisionMatrix.getDecisionNO(1) + POIDirection.get(i).getWeight());
                        break;

                    case East:
                        decisionMatrix.setDecisionE(1, decisionMatrix.getDecisionE(1) + POIDirection.get(i).getWeight());
                        decisionMatrix.setDecisionNE(1, decisionMatrix.getDecisionNE(1) + POIDirection.get(i).getWeight());
                        decisionMatrix.setDecisionSE(1, decisionMatrix.getDecisionSE(1) + POIDirection.get(i).getWeight());
                        break;

                    default:
                        break;
                }
            }
        }

        //TREATMENT HTH
        for (int i = 0; i < POIHandToHand.size(); i++) {
            if (!POIHandToHand.isEmpty()) // secure test
            {
                switch (POIHandToHand.get(i)) {
                    case NorthWest:
                        decisionMatrix.setDecisionNO(2, Parameter.getActionWeight());
                        break;
                    case North:
                        decisionMatrix.setDecisionN(2, Parameter.getActionWeight());
                        break;
                    case NorthEast:
                        decisionMatrix.setDecisionNE(2, Parameter.getActionWeight());
                        break;
                    case West:
                        decisionMatrix.setDecisionO(2, Parameter.getActionWeight());
                        break;
                    case East:
                        decisionMatrix.setDecisionE(2, Parameter.getActionWeight());
                        break;
                    case SouthWest:
                        decisionMatrix.setDecisionSO(2, Parameter.getActionWeight());
                        break;
                    case South:
                        decisionMatrix.setDecisionS(2, Parameter.getActionWeight());
                        break;
                    case SouthEast:
                        decisionMatrix.setDecisionSE(2, Parameter.getActionWeight());
                        break;
                }
            }
        }

        // 4th POST-TREATMENT
        // Handling Resources in Hand : 
        // no move POI Around if already Resources in hand
        if (hasMaxRessource()) {
            int[] zeroVector = {0, 0, 0, 0, 0, 0, 0, 0};
            decisionMatrix.multiplyVectorToRow(1, zeroVector);
        }

        //Treatment goTarget
        //Checks the actual path and target, and get new ones if any problem
        //if no target or no path available return false.
        boolean pathOK = validatePath();

        if (pathOK) {
            //decisionMatrix set weight to target direction
            DirectDirection nextDirection = this.getNextPathLocationDirection();

            if (nextDirection.equals(DirectDirection.None)) {
                //System.out.println("Arrived to destination");
                //System.out.println("Target :");
                //this.getTarget().displayInTerminal();
                //System.out.println("Being position : ");
                //this.getLocation().displayInTerminal();

                this.myClan.reportLocation(this.getTarget(), this.getActivity());
                this.setTargetLocation(null);
                //Remove target
            } else {
                decisionMatrix.majWeight(nextDirection, 3, Parameter.getTargetWeight());
            }

        }

        // POST TREATMENT -- No Collision, No Moving into Obstacle
        // NULLIFY WEIGHT OF OBSTACLE SQUARES

        if (decisionMatrix.isZeroExceptRowGoTarget()) {
            int[] randomMove = {1, 1, 1, 1, 1, 1, 1, 1};
            decisionMatrix.addVectorToRow(1, randomMove);
        }

        DirectDirection direction;

        int[] isSquareOk = {0, 0, 0, 0, 0, 0, 0, 0};
        int[] isEscapeOk = {0, 0, 0, 0, 0, 0, 0, 0};

        for (Square square : directEnvironement) {
            direction = this.getLocation().whatDirectDirectionWith(square.getLocation());

            switch (direction) {
                case NorthWest:
                    isSquareOk[0] = (square.isObstacle()) ? 0 : 1;
                    break;
                case North:
                    isSquareOk[1] = (square.isObstacle()) ? 0 : 1;
                    break;
                case NorthEast:
                    isSquareOk[2] = (square.isObstacle()) ? 0 : 1;
                    break;
                case West:
                    isSquareOk[3] = (square.isObstacle()) ? 0 : 1;
                    break;
                case East:
                    isSquareOk[4] = (square.isObstacle()) ? 0 : 1;
                    break;
                case SouthWest:
                    isSquareOk[5] = (square.isObstacle()) ? 0 : 1;
                    break;
                case South:
                    isSquareOk[6] = (square.isObstacle()) ? 0 : 1;
                    break;
                case SouthEast:
                    isSquareOk[7] = (square.isObstacle()) ? 0 : 1;
                    break;
                default:
                    break;
            }
        }

        isEscapeOk[0] = isSquareOk[7];
        isEscapeOk[1] = isSquareOk[6];
        isEscapeOk[2] = isSquareOk[5];
        isEscapeOk[3] = isSquareOk[4];
        isEscapeOk[4] = isSquareOk[3];
        isEscapeOk[5] = isSquareOk[2];
        isEscapeOk[6] = isSquareOk[1];
        isEscapeOk[7] = isSquareOk[0];

        decisionMatrix.multiplyVectorToRow(3, isSquareOk);
        decisionMatrix.multiplyVectorToRow(1, isSquareOk);
        decisionMatrix.multiplyVectorToRow(0, isEscapeOk);

        if (decisionMatrix.isZero()) {
            System.out.println("Matrix Still zero");
            /*
            System.out.println("Check if surrounded by obstacles : ");
            for (int i : isSquareOk) {
                System.out.println(i);
            }
            
            decisionMatrix.displayInTerminal();
            
            System.out.println("Second step ");*/
            
            //Second step for special cases : matrix not zero, but zero after treatment obstacles
            int[] randomMove = {1, 1, 1, 1, 1, 1, 1, 1};
            decisionMatrix.addVectorToRow(1, randomMove);

            decisionMatrix.multiplyVectorToRow(1, isSquareOk);
            
            //decisionMatrix.displayInTerminal();


        }
        //End post treatment

        Action action = null;
        if (!decisionMatrix.isZero()) {
            // C ACTION DEPENDING ON DECISIONMATRIX
            decisionMatrix.sumInStats();
            action = decisionMatrix.chooseAction();

            //VERIFICATION POUR DEBUG
            Location l = new Location(this.getLocation().getXPosition(), this.getLocation().getYPosition());
            Square s = myClan.debugGetSquare(action.getDirectDirection(), l);
            if ((action.getDecision() == 1) && s.isObstacle()) {
                System.out.println("**************************************************************");
                System.out.println("Being " + this.getId() + " is trying to go to occupied position :");
                s.displayLongInfoInTerminal();

                System.out.println("Square is obstacle : " + s.isObstacle());

                System.out.println("\nDecisionMatrix : ");
                decisionMatrix.displayInTerminal();

                System.out.println("\n\nVerification du postTraitement : ");
                for (int i = 0; i < isSquareOk.length; i++) {
                    System.out.println(" i : " + i + " isOk " + isSquareOk[i] + " | ");
                }
                System.out.println("\nAction choisie :");
                System.out.println("direction : " + action.getDirectDirection().name() + " Action type : " + action.getDecision());
                System.out.println("**************************************************************\n");
            }
            //FIN VERIFICATION POUR DEBUG

        } //Else : do nothing
        else {
            //VERIFICATION POUR DEBUG
            System.out.println("DM IS null");

            System.out.println("\ndecisionMatrix : ");
            decisionMatrix.displayInTerminal();

            System.out.println("\n\nisSquareOk : ");
            for (int i = 0; i < isSquareOk.length; i++) {
                System.out.println(" direction : " + i + " isOk " + isSquareOk[i]);
            }

            System.out.println("\nNb PoiAround : " + POIDirection.size());
            System.out.println("Nb PoiHth : " + POIHandToHand.size());
            System.out.println("Nb DangerAround : " + dangerDirection.size());

            if (this.getTarget() != null) {
                System.out.println("\nTarget : ");
                this.getTarget().displayInTerminal();
            } else {
                System.out.println("\nNo target");
            }

            System.out.println("\nInfos Being : ");
            this.displayInfoInTerminal();
            //FIN VERIFICATION POUR DEBUG
        }

        return action;

    }

    public void doSpecificAction(Action action, Square actionSquare) {

        if (this.hasMaxRessource()) {
            System.out.println("Being " + this.getId() + "is trying to doSpecificAction without ressource");
            // should not reach : no 'doSpecificAction' is already resource on himself.
            return;
        }

        switch (this.activity) {
            case Hunter:
                this.pickResourceFromBeingInSquare(actionSquare);
                break;
            case Stoneminer:
            case Goldminer:
            case Lumberjack:
                this.pickResourceFromResourceInSquare(actionSquare);
                break;
            default:
                break;

        }
    }

    //A TESTER : Cohérence vue
    public void pickResourceFromBeingInSquare(Square actionSquare) {
        if (actionSquare.getBeingReference() == null) {
            // no being in ??
            // should not reach
            System.out.println("Being " + this.getId() + "is trying to pickResource from a square without being");
            return;
        }

        int amountResourceInSquare = actionSquare.getBeingReference().getResourceBrought().getAmount();
        int amountToGet = Math.min(amountResourceInSquare, Parameter.getMaxAmountBrought());
        this.getResourceBrought().setAmount(amountToGet);
        // refresh new resource amount in square
        actionSquare.getBeingReference().getResourceBrought().setAmount(amountResourceInSquare - amountToGet);
    }

    public void pickResourceFromResourceInSquare(Square actionSquare) {
        if (actionSquare.getResource() == null) {
            // No resource on this square?
            System.out.println("Being " + this.getId() + "is trying to pickResource from the following square without resource");
            //System.out.println("Action Square : ");
            actionSquare.displayLongInfoInTerminal();
            return;
        }
        int amountResourceInSquare = actionSquare.getResource().getAmount();
        int amountToGet = Math.min(amountResourceInSquare, Parameter.getMaxAmountBrought());
        this.getResourceBrought().setAmount(amountToGet);

        // refresh new resource amount in square
        actionSquare.getResource().setAmount(amountResourceInSquare - amountToGet);
        Statistics.majResource(amountToGet, actionSquare.getResource().getType());

    }

    public ArrayList<DirectionWeighted> dangerAround(ArrayList<Square> environmentInRadius) {
        // declaration
        // res - final res to return.
        ArrayList<DirectionWeighted> res = new ArrayList<DirectionWeighted>();
        // resAux : contains all the Direction (possible doublon) with weight.
        ArrayList<DirectionWeighted> resAux = new ArrayList<DirectionWeighted>();
        // the beings in the environment.
        ArrayList<Being> beingsInEnv = getBeingsInEnvironment(environmentInRadius);
        // the DirecionWeighted to be added to the final result
        DirectionWeighted WestWeight = new DirectionWeighted(Direction.West, 0);
        DirectionWeighted NorthWeight = new DirectionWeighted(Direction.North, 0);
        DirectionWeighted EastWeight = new DirectionWeighted(Direction.East, 0);
        DirectionWeighted SouthWeight = new DirectionWeighted(Direction.South, 0);

        // code
        for (int i = 0; i < beingsInEnv.size(); i++) {
            if (beingsInEnv.get(i).isAnimal()) {
                // check what are the dangers for a Villager
                if (((Animal) beingsInEnv.get(i)).getType() == AnimalType.Lion) {
                    // get the directions in which the danger is
                    ArrayList<Direction> directionList = this.getLocation().getRelativeDirection(beingsInEnv.get(i).getLocation());

                    // get the distance between this & the danger
                    int weight = Parameter.getMaxFearDistance() - this.getLocation().getRelativeDistance(beingsInEnv.get(i).getLocation());
                    for (int j = 0; j < directionList.size(); j++) // add danger with weight to resAux
                    {
                        DirectionWeighted directionWeighted = new DirectionWeighted(directionList.get(j), weight);
                        resAux.add(directionWeighted);
                    }
                }
            }
        }

        // transfer resAux to res with appropriate weights
        for (int i = 0; i < resAux.size(); i++) {
            switch (resAux.get(i).getDirection()) {
                case West:
                    WestWeight.setWeight(WestWeight.getWeight() + resAux.get(i).getWeight());
                    break;
                case North:
                    NorthWeight.setWeight(NorthWeight.getWeight() + resAux.get(i).getWeight());
                    break;
                case East:
                    EastWeight.setWeight(EastWeight.getWeight() + resAux.get(i).getWeight());
                    break;
                case South:
                    SouthWeight.setWeight(SouthWeight.getWeight() + resAux.get(i).getWeight());
                    break;
                default:
                    break;
            }
        }
        res.add(WestWeight);
        res.add(NorthWeight);
        res.add(EastWeight);
        res.add(SouthWeight);
        return res;
    }

    public ArrayList<DirectionWeighted> pointsOfInterestAround(ArrayList<Square> environmentInRadius) {
        // declaration
        // res - final res to return.
        ArrayList<DirectionWeighted> res = new ArrayList<DirectionWeighted>();
        // resAux : contains all the Direction (possible doublon) with weight.
        ArrayList<DirectionWeighted> resAux = new ArrayList<DirectionWeighted>();
        // the DirecionWeighted to be added to the final result
        DirectionWeighted WestWeight = new DirectionWeighted(Direction.West, 0);
        DirectionWeighted NorthWeight = new DirectionWeighted(Direction.North, 0);
        DirectionWeighted EastWeight = new DirectionWeighted(Direction.East, 0);
        DirectionWeighted SouthWeight = new DirectionWeighted(Direction.South, 0);

        // code
        switch (this.activity) {
            // HUNTER
            case Hunter:
                // get the beings in environment.
                ArrayList<Being> beingsInEnv = getBeingsInEnvironment(environmentInRadius);

                // check if these are Does or Elephants
                for (int i = 0; i < beingsInEnv.size(); i++) {
                    if (beingsInEnv.get(i).isAnimal()) {
                        // check what can hunt a hunter.
                        if ((((Animal) beingsInEnv.get(i)).getType() == AnimalType.Doe)
                                || (((Animal) beingsInEnv.get(i)).getType() == AnimalType.Elephant)) {
                            // get the directions in which the target is
                            ArrayList<Direction> directionList = this.getLocation().getRelativeDirection(beingsInEnv.get(i).getLocation());

                            // get the distance between this & the target
                            int weight = Parameter.getMaxDistance() - this.getLocation().getRelativeDistance(beingsInEnv.get(i).getLocation());
                            for (int j = 0; j < directionList.size(); j++) // add danger with weight to resAux
                            {
                                // update resAux
                                DirectionWeighted directionWeighted = new DirectionWeighted(directionList.get(j), weight);
                                resAux.add(directionWeighted);
                            }
                        }
                    }
                }
                break;

            // LUMBERJACK
            case Lumberjack:
                // get the wood around
                ArrayList<Square> woodSquareInEnv = getSquareTypeInEnvironment(environmentInRadius, SquareType.Wood);
                for (int i = 0; i < woodSquareInEnv.size(); i++) {
                    // get the direction of the wood.
                    ArrayList<Direction> directionList = this.getLocation().getRelativeDirection(woodSquareInEnv.get(i).getLocation());

                    // get the distance of wood to this.
                    int weight = this.getLocation().getRelativeDistance(woodSquareInEnv.get(i).getLocation());
                    for (int j = 0; j < directionList.size(); j++) // add wood direction with weight to resAux
                    {
                        // modifying resAux
                        DirectionWeighted directionWeighted = new DirectionWeighted(directionList.get(j), weight);
                        resAux.add(directionWeighted);
                    }
                }
                break;

            // GOLDMINER
            case Goldminer:
                // get the gold around
                ArrayList<Square> goldSquareInEnv = getSquareTypeInEnvironment(environmentInRadius, SquareType.Gold);
                for (int i = 0; i < goldSquareInEnv.size(); i++) {
                    // get the direction of the gold.
                    ArrayList<Direction> directionList = this.getLocation().getRelativeDirection(goldSquareInEnv.get(i).getLocation());

                    // get the distance of gold to this.
                    int weight = this.getLocation().getRelativeDistance(goldSquareInEnv.get(i).getLocation());
                    for (int j = 0; j < directionList.size(); j++) // add wood direction with weight to resAux
                    {
                        // modifying resAux
                        DirectionWeighted directionWeighted = new DirectionWeighted(directionList.get(j), weight);
                        resAux.add(directionWeighted);
                    }
                }
                break;

            // STONEMINER	
            case Stoneminer:
                // get the stone around
                ArrayList<Square> stoneSquareInEnv = getSquareTypeInEnvironment(environmentInRadius, SquareType.Stone);
                for (int i = 0; i < stoneSquareInEnv.size(); i++) {
                    // get the direction of the stone.
                    ArrayList<Direction> directionList = this.getLocation().getRelativeDirection(stoneSquareInEnv.get(i).getLocation());

                    // get the distance of stone to this.
                    int weight = this.getLocation().getRelativeDistance(stoneSquareInEnv.get(i).getLocation());
                    for (int j = 0; j < directionList.size(); j++) // add wood direction with weight to resAux
                    {
                        // modifying resAux
                        DirectionWeighted directionWeighted = new DirectionWeighted(directionList.get(j), weight);
                        resAux.add(directionWeighted);
                    }
                }
                break;

            // BUILDER	
            case Builder:
                break;

        }

        // transfer resAux to res with appropriate weights
        for (int i = 0; i < resAux.size(); i++) {
            switch (resAux.get(i).getDirection()) {
                case West:
                    WestWeight.setWeight(WestWeight.getWeight() + resAux.get(i).getWeight());
                    break;
                case North:
                    NorthWeight.setWeight(NorthWeight.getWeight() + resAux.get(i).getWeight());
                    break;
                case East:
                    EastWeight.setWeight(EastWeight.getWeight() + resAux.get(i).getWeight());
                    break;
                case South:
                    SouthWeight.setWeight(SouthWeight.getWeight() + resAux.get(i).getWeight());
                    break;
                default:
                    break;
            }
        }
        res.add(WestWeight);
        res.add(NorthWeight);
        res.add(EastWeight);
        res.add(SouthWeight);
        return res;
    }

    public ArrayList<DirectDirection> pointsOfIntestInHtH(ArrayList<Square> directNeighbours) {
        ArrayList<DirectDirection> res = new ArrayList<DirectDirection>();
        switch (this.activity) {
            case Hunter:
                res = getDirectDirectionOfType(ResourceType.Food, directNeighbours);
                break;
            case Lumberjack:
                // getDirectDirectionOfType(SquareType.Wood);
                res = getDirectDirectionOfType(ResourceType.Wood, directNeighbours);
                break;
            case Goldminer:
                // getDirectDirectionOfType(SquareType.Gold);
                res = getDirectDirectionOfType(ResourceType.Gold, directNeighbours);
                break;
            case Stoneminer:
                // getDirectDirectionOfType(SquareType.Stone);
                res = getDirectDirectionOfType(ResourceType.Stone, directNeighbours);
                break;
            case Builder:
                // DONT KNOW
                break;
            default:
                break;
        }

        return res;
    }

    public ArrayList<DirectDirection> getDirectDirectionOfType(ResourceType resourceType, ArrayList<Square> directNeighbours) {
        ArrayList<DirectDirection> res = new ArrayList<DirectDirection>();

        if (resourceType == ResourceType.Food) {
            for (int i = 0; i < directNeighbours.size(); i++) {
                if (directNeighbours.get(i).getBeingReference() != null) {
                    if (directNeighbours.get(i).getBeingReference().isAnimal()) {
                        DirectDirection dd = this.getLocation().whatDirectDirectionWith(directNeighbours.get(i).getLocation());
                        res.add(dd);
                    }
                }
            }
        } else // wood/stone/gold
        {
            for (int i = 0; i < directNeighbours.size(); i++) {
                if (directNeighbours.get(i).getResource() != null
                        && directNeighbours.get(i).getResource().getType() == resourceType) {
                    res.add(this.getLocation().whatDirectDirectionWith(directNeighbours.get(i).getLocation()));
                }
            }
        }
        return res;
    }

    // GETTER - SETTER
    public Clan getMyClan() {
        return myClan;
    }

    public void setMyClan(Clan myClan) {
        this.myClan = myClan;
    }

    private boolean validatePath() {
        boolean pathOK = false;
        boolean targetOK = false;

        // target OK means : target != null and is still availlable
        if (this.getTarget() != null && this.getMyClan().isTargetAvailable(this.getTarget(), this.getActivity())) {
            targetOK = true;
        } else { //get new target from clan       
            //if hasMaxRessource true => target = QG
            this.setTargetLocation(this.getMyClan().getNewTarget(this.activity, hasMaxRessource()));

            if (this.getTarget() != null) {
                targetOK = true;
            } else { //Else no target availlable.
                return false;
            }
        }

        //path OK means : location of the this being is in the path, last position of the path is the target

        boolean locationExist = false;

        for (Location l : this.getPath()) {
            if (l.compare(this.getLocation())) {
                locationExist = true;
            }
        }

        if (locationExist && this.getPath().get(this.getPath().size() - 1).compare(this.getTarget())) {
            pathOK = true;
        } else {
            //looking for a new path
            //System.out.println("Recalcul du path");
            this.setPath(this.myClan.getBoard().getPath(this.getLocation(), this.getTarget()));

            //verify the new path
            if (this.getPath().get(0).compare(this.getLocation())) {
                if (this.getPath().get(this.getPath().size() - 1).compare(this.getTarget())) {
                    pathOK = true;
                }
            }
        }

        return (pathOK && targetOK);
    }

    private void majMemory(ArrayList<Square> environmentInRadius) {

        //Obsolete ?
        /*if (this.getTarget() != null && this.getTarget().compare(this.getLocation())) {
         this.myClan.getMemory().remove(this.activity, this.getTarget());
         }*/

        for (Square s : environmentInRadius) {
            switch (s.getType()) {
                case Wood:
                    this.myClan.getMemory().addWood(s.getLocation());
                    break;
                case Gold:
                    this.myClan.getMemory().addGold(s.getLocation());
                    break;
                case Stone:
                    this.myClan.getMemory().addStone(s.getLocation());
                    break;
                case Water:
                    this.myClan.getMemory().addWater(s.getLocation());
                    break;
            }

            if (s.getBeingReference() != null && s.getBeingReference().isAnimal()) {
                this.myClan.getMemory().addAnimals(s.getBeingReference().getId(), s.getLocation());
            }
        }
    }

    //Version temporaire, équivalent a hasResource pour l'instant.
    private boolean hasMaxRessource() {
        boolean hasMaxRessource = false;
        if (this.getResourceBrought().getAmount() > 0) {
            hasMaxRessource = true;
        }
        return hasMaxRessource;
    }
}
